package com.only4play.common.utils;

import com.google.common.base.Strings;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.tika.Tika;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Objects;
import java.util.concurrent.Callable;

/**
 * 文件相关工具类
 *
 * @author liyuncong
 * @date 2023/11/06 14:36
 **/
public class FilesUtils {
    private static final String DEFAULT_MIME_TYPE = "application/octet-stream";
    private static final Tika TIKA_INSTANCE = new Tika();

    /**
     * 获取路径的父路径。
     *
     * @param path 路径
     * @return 父路径
     */
    public static Path getParent(Path path) {
        return Objects.isNull(path.getParent()) ? path : path.getParent();
    }

    /**
     * 获取路径的父路径。
     *
     * @param path 路径
     * @return 父路径
     */
    public static Path getParent(String path) {
        return getParent(Paths.get(path));
    }

    /**
     * 检查路径是否存在，不存在则创建.
     * 是文件夹路径，就创建到文件夹；
     * 是文件，就创建到文件的父目录。
     *
     * @param path        路径
     * @param isDirectory 是否是文件夹
     * @return true
     */
    public static boolean checkPath(Path path, boolean isDirectory) {
        Path parent = isDirectory ? path : getParent(path);
        if (!Files.exists(parent) || !Files.isDirectory(parent)) {
            try {
                Files.createDirectories(parent);
            } catch (FileAlreadyExistsException alreadyExistsException) {
                return true;
            } catch (IOException exception) {
//                log.error("Failed to create directory {}", parent, exception);
                return false;
            }
        }
        return true;
    }

    /**
     * 获取文件的md5值.
     *
     * @param path 文件路径
     * @return md5
     */
    public static String getChecksum(Path path) {
        try (InputStream inputStream = Files.newInputStream(path)) {
            return DigestUtils.md5Hex(inputStream);
        } catch (IOException exception) {
            return null;
        }
    }

    /**
     * 获取获取字符串的hash值.
     *
     * @param json 字符串
     * @return hash值
     */
    public static String getHash(String json) {
        return DigestUtils.sha256Hex(json);
    }

    /**
     * 根据文件名获取文件的mimetype.
     *
     * @param filename 文件名
     * @return mimetype
     */
    public static String getMimeType(String filename) {
        return getMimeType(() -> TIKA_INSTANCE.detect(filename));
    }

    /**
     * 根据文件获取文件的mimetype.
     *
     * @param file 文件
     * @return mimetype
     */
    public static String getMimeType(File file) {
        return getMimeType(() -> TIKA_INSTANCE.detect(file));

    }

    /**
     * 根据文件获取文件的mimetype.
     *
     * @param file MultipartFile文件
     * @return mimetype
     */
    public static String getMimeType(MultipartFile file) {
        final String contentType = file.getContentType();
        if (!Strings.isNullOrEmpty(contentType)
                && Objects.equals(DEFAULT_MIME_TYPE, contentType)) {
            return contentType;
        }
        return getMimeType(() -> TIKA_INSTANCE.detect(file.getInputStream()));
    }

    private static String getMimeType(Callable<String> action) {
        try {
            final String mimeType = action.call();
            return Strings.isNullOrEmpty(mimeType) ? DEFAULT_MIME_TYPE : mimeType;
        } catch (Throwable throwable) {
//            log.debug("parse file mime type error, return default mime type");
            return DEFAULT_MIME_TYPE;
        }
    }

}
